/*
 * @Author: wangke
 * @Date: 2025-04-20 22:07:43
 * @LastEditors: wangke
 * @LastEditTime: 2025-05-05 22:07:40
 * 
 */
#include "App_I2S.h"
#include <Arduino.h>
#include "App_Sd.h"
#include "PIN.h"



// Audio recording settings
#define SAMPLE_RATE 16000
#define RECORD_TIME_SECONDS 10
#define BUFFER_SIZE (SAMPLE_RATE * RECORD_TIME_SECONDS)


//用于存储录音的音频数据
uint8_t* AuDio_data = NULL;
size_t AuDio_len = 0;

 // Initialize I2S for audio output
 void I2S_Init() {
  i2s_config_t i2s_config_out = {
    .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX),
    .sample_rate = SAMPLE_RATE,
    .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
    .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
    .communication_format = I2S_COMM_FORMAT_STAND_I2S,
    .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
    .dma_buf_count = 16,
    .dma_buf_len = 1024,
    .use_apll = false,
    .tx_desc_auto_clear = true
  };
  i2s_pin_config_t pin_config = {
    .bck_io_num = I2S_OUT_BCLK,
    .ws_io_num = I2S_OUT_LRC,
    .data_out_num = I2S_OUT_DOUT,
    .data_in_num = -1
  };

  i2s_driver_install(I2S_OUT_PORT, &i2s_config_out, 0, NULL);
  i2s_set_pin(I2S_OUT_PORT, &pin_config);
  i2s_set_clk(I2S_OUT_PORT, SAMPLE_RATE, I2S_BITS_PER_SAMPLE_16BIT, I2S_CHANNEL_MONO);
}

void I2S_RecoderInit()
{
 // Initialize I2S for audio input
  i2s_config_t i2s_config_in = {
    .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),
    .sample_rate = SAMPLE_RATE,
    .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,  // 注意：INMP441 输出 32 位数据
    .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
    .communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_STAND_I2S),
    .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
    .dma_buf_count = 8,
    .dma_buf_len = 1024,
  };
  i2s_pin_config_t pin_config_in = {
    .bck_io_num = I2S_IN_BCLK,
    .ws_io_num = I2S_IN_LRC,
    .data_out_num = -1,
    .data_in_num = I2S_IN_DIN
  };
  i2s_driver_install(I2S_IN_PORT, &i2s_config_in, 0, NULL);
  i2s_set_pin(I2S_IN_PORT, &pin_config_in);

  AuDio_data = (uint8_t*)ps_malloc(BUFFER_SIZE * sizeof(int16_t));
}



int I2S_Read(char* data, int numData) {
  size_t bytes_readen;
  return i2s_read(I2S_IN_PORT, (char *)data, numData, &bytes_readen,portMAX_DELAY);
}

// Play audio data using MAX98357A
void I2S_Write(uint8_t* data, int numData) {
  if(numData > 0) {
    size_t bytes_written = 0;
    i2s_write(I2S_OUT_PORT, (int16_t*)data, numData,&bytes_written, portMAX_DELAY);
  }
}


// Play audio data using MAX98357A
void playAudio(uint8_t* audioData, size_t audioDataSize) {
  if (audioDataSize > 0) {
    // 发送
    size_t bytes_written = 0;
    i2s_write(I2S_OUT_PORT, (int16_t*)audioData, audioDataSize, &bytes_written, portMAX_DELAY);
  }
}

void clearAudio(void) {
  // 清空I2S DMA缓冲区
  i2s_zero_dma_buffer(I2S_OUT_PORT);
}


void Audio_Record(void)
{
    i2s_read(I2S_IN_PORT, AuDio_data, BUFFER_SIZE, &AuDio_len, 2000);
}



//结构体去除wav音频数据头
typedef struct{
  char riff[4];            // "RIFF"
  uint32_t chunkSize;
  char wave[4];            // "WAVE"
  char fmt[4];             // "fmt "
  uint32_t subchunk1Size;  // 通常为 16
  uint16_t audioFormat;    // PCM = 1
  uint16_t numChannels;
  uint32_t sampleRate;
  uint32_t byteRate;
  uint16_t blockAlign;
  uint16_t bitsPerSample;
  char dataHeader[4];      // "data"
  uint32_t dataSize;       // PCM数据的总字节数
}WAVHeader;


uint8_t* SD_pcmData = NULL;
int SD_pcmDataSize = 0;
//从SD卡读取wav音频并转为PCM
void read_wav(fs::FS &fs, const char * path) {
    File file = fs.open(path);
    if(!file){
        return;
    }

    WAVHeader header;
    if (file.read((uint8_t *)&header, sizeof(WAVHeader)) != sizeof(WAVHeader)) {
    // Serial.println("读取 WAV 头失败");
        file.close();
        return;
    } 

    if (strncmp(header.riff, "RIFF", 4) != 0 || strncmp(header.wave, "WAVE", 4) != 0 || strncmp(header.dataHeader, "data", 4) != 0) {
    // Serial.println("不是有效的 WAV PCM 文件");
        file.close();
        return;
    }

    SD_pcmData = (uint8_t*)ps_malloc(header.dataSize);
    if (!SD_pcmData) {
        file.close();
        return;
    }

    // 从文件当前指针位置开始读 PCM 数据
    SD_pcmDataSize = file.read(SD_pcmData, header.dataSize); 
    if (SD_pcmDataSize != header.dataSize) {
        free(SD_pcmData);
        file.close();
        return;
    }

    file.close();
}



void play_SD_video(const char * path)
{
    read_wav(SD, path);
    playAudio(SD_pcmData, SD_pcmDataSize);
    delay(800);
    clearAudio();
}